# This file is part of Email-Reminder.
#
# Email-Reminder is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3 of the
# License, or (at your option) any later version.
#
# Email-Reminder is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Email-Reminder; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.

package EmailReminder::EventStore;

# Base class for all of the event stores.
# 
# This class should never be used directly, use a derived class instead.

use strict;
use warnings;

use Gtk2;
use Glib::Object::Subclass
    Glib::Object::,
    interfaces => [ Gtk2::TreeModel:: ],
    ;

use constant TRUE => 1;
use constant FALSE => 0; 

# Column indices
my $ID_INDEX = 0;

sub init
{
    my ($this) = @_;
    $this->{EVENTS} = [];
    $this->{NB_EVENTS} = 0;
}

sub add_event
{
    my ($this, $event) = @_;
    push (@{$this->{EVENTS}}, $event);
    my $path = Gtk2::TreePath->new_from_string($#{$this->{EVENTS}});
    my $iter = $this->get_iter($path);
    $this->row_inserted($path, $iter);
    $this->{NB_EVENTS}++;
    return $path;
}

sub delete_event
{
    my ($this, $path) = @_;
    my $index = $path->get_indices();

    $this->{EVENTS}->[$index]->unlink();
    splice(@{$this->{EVENTS}}, $index, 1);
    $this->{NB_EVENTS}--;

    # Send the necessary signals
    $this->row_deleted($path);
    if ($this->{NB_EVENTS} > 0) {
	my $iter = $this->get_iter($path);
        return unless defined($iter);

	$iter = $this->iter_next($iter);
	while (defined($iter)) {
	    my $path = $this->get_path($iter);
	    $this->row_changed($path, $iter);
	    $iter = $this->iter_next($iter);
	}
    }
}

sub get_nb_events
{
    my ($this) = @_;
    return $this->{NB_EVENTS};
}

sub get_event
{
    my ($this, $path) = @_;
    my $index = $path->get_indices();
    return $this->{EVENTS}->[$index];
}

sub get_events
{
    my ($this) = @_;
    return $this->{EVENTS};
}

sub get_event_column
{
    my ($this, $event, $col) = @_;

    if ($col == $ID_INDEX) {
        return $event->get_id();
    }
    else {
        warn "Column '$col' is not a valid column.\n";
        return undef;
    }
}

sub set_event_column
{
    my ($this, $event, $col, $new_value) = @_;
    if ($col == $ID_INDEX) {
        warn "The ID column is read-only.\n";
    }
    else {
        warn "Column '$col' is not a valid column for value '$new_value'.\n";
    }
}

sub set_value
{
    my ($this, $path, $column, $new_value) = @_;
    my $row_index = $path->get_indices();
    my $event = $this->{EVENTS}->[$row_index];
    $this->set_event_column($event, $column, $new_value);
}

########################
# Tree Model Interface #
########################

sub GET_FLAGS
{
    return 'list-only';
}

sub GET_N_COLUMNS
{
    my $this = shift;
    return $this->{NB_COLUMNS};
}

sub GET_COLUMN_TYPE
{
    return 'Glib::String';
}

sub GET_ITER
{
    my ($this, $path) = @_;

    my $index = $path->get_indices();
    my $iter = [ $index, $index, undef, undef ];

    # Find the first non-deleted item
    unless (exists($this->{EVENTS}->[$index])) {
	$iter = $this->ITER_NEXT($iter);
    }

    return $iter;
}

sub GET_PATH
{
    my ($this, $iter) = @_;
    return Gtk2::TreePath->new($iter->[1]);
}

sub GET_VALUE
{
    my ($this, $iter, $column) = @_;
    my $index = $iter->[1];
    my $event = $this->{EVENTS}->[$index];
    return "(missing)" unless defined($event); # TODO: remove this
    my $value = $this->get_event_column($event, $column);
    return defined($value) ? $value : "";
}

sub ITER_NEXT
{
    my ($this, $iter) = @_;
    my $index = $iter->[1] + 1;

    # Skip over deleted items
    while ($index < @{$this->{EVENTS}}) {
	if (exists($this->{EVENTS}->[$index])) {
	    return [ $index, $index, undef, undef ];
	}
	$index++;
    }

    return undef;
}

# This is a list store, there are no children

sub ITER_CHILDREN
{
    return undef;
}

sub ITER_HAS_CHILD
{
    return FALSE;
}

sub ITER_N_CHILDREN
{
    return 0;
}

sub ITER_NTH_CHILD
{
    return undef;
}

sub ITER_PARENT
{
    return undef;
}

1;
